package com.honeybees.framework.common.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.time.StopWatch;

/**
 * <DL>
 * <DT><B> 集合工具类 </B></DT>
 * <p>
 * <DD>得到两个集合的交集，List累加，得到Map的值等。</DD>
 * </DL>
 * <p>
 *
 * @author 李远明
 * @since 2014-04-14 09:47:39
 */
public class CollectionUtils {

    // public static Logger logger = LoggerFactory.getLogger(CollectionUtils.class);

    /**
     * <DL>
     * <DT><B> 计算两个集合的交集 </B></DT>
     * <p>
     * <DD>详细介绍</DD>
     * </DL>
     * <p>
     *
     * @param <T>         集合中的元素的类型
     * @param collection1 第一个集合
     * @param collection2 第二个集合
     * @return 两个集合的交集： collection1 ∩ collection2
     * @version 2014-04-14 09:48:05
     */
    public static <T> Collection<T> calcIntersection(Collection<T> collection1, Collection<T> collection2) {
        Set<T> resultSet = new HashSet<T>();
        if (null == collection1 || null == collection2 || collection1.size() == 0 || collection2.size() == 0)
            return resultSet;
        CollectionCouple<T> couple = getCouple(collection1, collection2);
        Set<T> set = (Set<T>) couple.reference;
        for (T t : couple.contrast) {
            if (set.contains(t)) {
                resultSet.add(t);
            }
        }
        return resultSet;
    }

    private static <T> CollectionCouple<T> getCouple(Collection<T> collection1, Collection<T> collection2) {
        CollectionCouple<T> couple = new CollectionCouple<T>();
        boolean greater = collection1.size() > collection2.size();
        if (collection1 instanceof Set<?> && collection2 instanceof Set<?>) {
            couple.reference = greater ? collection1 : collection2;
            couple.contrast = greater ? collection2 : collection1;
            couple.hasSet = true;
        } else if (collection1 instanceof Set<?>) {
            couple.reference = collection1;
            couple.contrast = collection2;
            couple.hasSet = true;
        } else if (collection2 instanceof Set<?>) {
            couple.reference = collection2;
            couple.contrast = collection1;
            couple.hasSet = true;
        } else {
            couple.reference = greater ? collection2 : collection1;
            couple.contrast = greater ? collection1 : collection2;
        }
        couple.reference = couple.hasSet ? (Set<T>) couple.reference : new HashSet<T>(couple.reference);
        return couple;
    }

    /**
     * <DL>
     * <DT><B> 累加List的值（Accumulate） </B></DT>
     * <p>
     * <DD>适用于表格列的值累加</DD>
     * </DL>
     * <p>
     *
     * @param amtList 表格列的值
     * @return List的值的累加之和
     * @version 2014-04-15 21:20:54
     */
    public static <T> String sum(List<T> amtList) {
        if (amtList == null) {
            return "";
        }
        String sum = "0";
        for (int i = 0, s = amtList.size(); i < s; i++) {
            String ss = amtList.get(i).toString();
            sum = MathUtils.add(sum, ss);
        }
        return String.valueOf(sum);
    }

    /**
     * <DL>
     * <DT><B> 过滤List的NULL </B></DT>
     * <p>
     * <DD>详细介绍</DD>
     * </DL>
     * <p>
     *
     * @param columnList 表格列的数据
     * @return
     * @version 2014-04-16 11:16:35
     */
    public static List<Object> nullFilter(List<Object> columnList) {
        List<Object> nonNullList = new ArrayList<Object>();

        for (int i = 0, s = columnList.size(); i < s; i++) {
            Object ss = columnList.get(i);

            if (null == ss) {
                ss = "";
            }
            nonNullList.add(ss);
        }
        return nonNullList;
    }

    /**
     * <DL>
     * <DT><B> 根据Map的键值对过滤出List中包含Map的对象中符合条件的列表 </B></DT>
     * <p>
     * <DD>详细介绍</DD>
     * </DL>
     * <p>
     *
     * @param mapList  待过滤的List对象
     * @param mapKey   Map的键
     * @param mapValue Map的键对应的值
     * @return 过滤出的符合条件的列表
     * @throws Exception
     * @version 2014-06-06 09:52:28
     */
    public static List<Map<String, Object>> mapListFilter(List<Map<String, Object>> mapList, String mapKey,
                                                          String mapValue) throws Exception {
        List<Map<String, Object>> rList = new ArrayList<Map<String, Object>>();

        if (mapList == null || mapList.size() == 0) {
            return rList;
        }

        try {
            for (Map<String, Object> map : mapList) {
                String val = (String) map.get(mapKey);
                if (val.equals(mapValue)) {
                    rList.add(map);
                }
            }
        } catch (Exception e) {
            throw new Exception("Map中不含该键：" + mapKey);
        }
        // System.out.println(rList);
        return rList;
    }

    /**
     * <DL>
     * <DT><B> 从Map中获取到<code>key</code>对应的值 </B></DT>
     * <p>
     * <DD>如果Map为null，或者Map不包含<code>key</code>，则抛异常。</DD>
     * </DL>
     * <p>
     *
     * @param context Map
     * @param key     键名
     * @return key对应的值
     * @throws Exception 可能发生的异常
     * @author 李远明
     * @version 2014-12-11 17:30:33
     */
    public static <K, V> Object getMapValue(Map<K, V> context, Object key) throws Exception {
        Object retInfo;
        if (context == null) { // || key == null
            throw new Exception("Map不能为null"); // 或key
        } else {
            if (!context.containsKey(key)) {
                // throw new Exception("Map中不存在该键：" + key);
                retInfo = "";
            } else {
                Object o = context.get(key);
                if (o == null) {
                    retInfo = "";
                } else {
                    retInfo = o;
                }
            }
        }
        return retInfo;
    }

    /**
     * <DL>
     * <DT><B> 对List中包含Map的数据结构进行“升序”排序 </B></DT>
     * <p>
     * <DD></DD>
     * </DL>
     * <p>
     *
     * @param mapList List&lt;Map&lt;K,V&gt;&gt;
     * @param key     Map的键
     * @author 李远明
     * @version 2015-01-25 20:55:28
     */
    public static <K, V> void mapAscSort(List<Map<K, V>> mapList, String key) {
        Collections.sort(mapList, new MapComparator<K, V>(key, "ASC"));
    }

    /**
     * <DL>
     * <DT><B> 对List中包含Map的数据结构进行“降序”排序 </B></DT>
     * <p>
     * <DD>功能描述</DD>
     * </DL>
     * <p>
     *
     * @param mapList List&lt;Map&lt;K,V&gt;&gt;
     * @param key     Map的键
     * @author 李远明
     * @version 2015-01025 20:55:40
     */
    public static <K, V> void mapDescSort(List<Map<K, V>> mapList, String key) {
        Collections.sort(mapList, new MapComparator<K, V>(key, "DESC"));
    }

    /**
     * <DL>
     * <DT><B> 求集合的交集 </B></DT>
     * <p>
     * <DD>功能描述</DD>
     * </DL>
     * <p>
     *
     * @param collection1
     * @param collection2
     * @return
     * @author 李远明
     * @version 2015年5月29日 下午3:06:53
     * @see List#retainAll(Collection)
     */
    public static <T> Collection<T> calcIntersection2(Collection<T> collection1, Collection<T> collection2) {
        List<T> list1 = new ArrayList<T>(collection1);
        List<T> list2 = new ArrayList<T>(collection2);
        list1.retainAll(list2);
        return list1;
    }

    public static void main(String[] args) {
        StopWatch sw = new StopWatch();
        sw.start();
        String[] c1 = new String[]{"0", "3", "5", "7", "8", "12", "2"};
        String[] c2 = new String[]{"1", "4", "6", "7", "8", "10"};

        Collection<String> identicalValues = calcIntersection(Arrays.asList(c1), Arrays.asList(c2));
        System.out.println(identicalValues);
        sw.stop();
        System.out.println(sw.getTime());
        sw.reset();
        sw.start();
        Collection<String> calcIntersection = calcIntersection2(Arrays.asList(c1), Arrays.asList(c2));
        System.out.println(calcIntersection);
        sw.stop();
        System.out.println(sw.getTime());
    }
}

/**
 * <DL>
 * <DT><B> 取两个集合的交集 </B></DT>
 * <p>
 * <DD>com.kedao.api.util.CollectionCouple</DD>
 * </DL>
 * <p>
 * Copyright (C) All rights reserved.
 * <p>
 *
 * @param <T>
 * @author <a href="mailto:ijLee89@163.com"> JacobLee </a>
 * @since 2015-01-06 14:40:24
 */
class CollectionCouple<T> {

    /**
     * 保存用于参照的集合，一个Set对象。
     *
     * @see #contrast
     */
    Collection<T> reference;
    /**
     * 与<code>reference</code>进行参照
     *
     * @see #reference
     */
    Collection<T> contrast;
    /**
     * 两个集合中是否有一个是 {@link java.util.Set} 类型的集合。
     */
    boolean hasSet;

    @Override
    public String toString() {
        String msg = "CollectionCouple[" + contrast.toArray() + ", " + reference.toArray() + ", isSet: " + hasSet;
        return msg.toString();
    }

}

/**
 * <DL>
 * <DT><B> 对List中包含Map的数据结构进行排序 </B></DT>
 * <p>
 * <DD>用 Comparator 是策略模式（strategy design pattern），就是不改变对象自身，而用一个策略对象（strategy object）来改变它的行为。</DD>
 * </DL>
 * <p>
 * Copyright (C) All rights reserved.
 * <p>
 *
 * @param <K>
 * @param <V>
 * @author <a href="mailto:ijLee89@163.com"> JacobLee </a>
 * @see Comparable
 * @since 2015-01-25 20:43:45
 */
class MapComparator<K, V> implements Comparator<Map<K, V>> {

    public String keyName;
    public String order;

    public MapComparator(String keyName, String order) {
        super();
        this.keyName = keyName;
        this.order = order;
    }

    public String getKeyName() {
        return keyName;
    }

    public void setKeyName(String keyName) {
        this.keyName = keyName;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

    // @Override
    public int compare(Map<K, V> o1, Map<K, V> o2) {
        // TODO Auto-generated method stub

        String val1 = o1.get(keyName).toString();
        String val2 = o2.get(keyName).toString();

        int flag = 0;
        if ("ASC".equalsIgnoreCase(order)) {
            flag = val1.compareTo(val2);
        } else if ("DESC".equalsIgnoreCase(order)) {
            flag = val2.compareTo(val1);
        } else {
            flag = val1.compareTo(val2);
        }
        return flag;
    }

}
